﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EFCachingProvider.Caching;
using System.Web;
using System.Web.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
using System.Security.Cryptography;



namespace EFCachingProvider.Web
{
    public class EntLibCache : ICache
    {

        private const string DependentEntitySetPrefix = "dependent_entity_set_";
        // private HttpContext httpContext;

        //public EntLibCache()
        //    : this(null)
        //{
        //}

        //public EntLibCache(HttpContext httpContext)
        //{
        //    this.httpContext = httpContext;
        //}

        //2种建立CacheManager的方式
        //ICacheManager cache = EnterpriseLibraryContainer.Current.GetInstance<ICacheManager>();
        private static ICacheManager cache = CacheFactory.GetCacheManager();


        public bool GetItem(string key, out object value)
        {
            key = GetCacheKey(key);
            value = cache.GetData(key);

            return value != null;
        }

        public void PutItem(string key, object value, IEnumerable<string> dependentEntitySets, TimeSpan slidingExpiration, DateTime absoluteExpiration)
        {
            key = GetCacheKey(key);


            //foreach (var entitySet in dependentEntitySets)
            //{
            //    this.EnsureEntryExists(DependentEntitySetPrefix + entitySet);
            //}

            try
            {


                CacheDependency cd = new CacheDependency(new string[0], dependentEntitySets.Select(c => DependentEntitySetPrefix + c).ToArray());
                cache.Add(key, value);
            }
            catch (Exception)
            {
                // there's a possibility that one of the dependencies has been evicted by another thread
                // in this case just don't put this item in the cache
            }
        }

        public void InvalidateSets(IEnumerable<string> entitySets)
        {
            foreach (string entitySet in entitySets)
            {
                cache.Remove(DependentEntitySetPrefix + entitySet);
            }
        }

        public void InvalidateItem(string key)
        {
            key = GetCacheKey(key);
            cache.Remove(key);
        }


        /// <summary>
        /// Hashes the query to produce cache key..
        /// </summary>
        /// <param name="query">The query.</param>
        /// <returns>Hashed query which becomes a cache key.</returns>
        private static string GetCacheKey(string query)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(query);
            string hashString = Convert.ToBase64String(MD5.Create().ComputeHash(bytes));
            return hashString;
        }

        private void EnsureEntryExists(string key)
        {


            if (cache.GetData(key) == null)
            {
                try
                {
                    cache.Add(key, key);
                }
                catch (Exception)
                {
                    // ignore exceptions.
                }
            }
        }
    }
}
